//******************************************************************
//******************************************************************
//**********          ANts Peer To Peer Sources        *************
//
// ANts P2P realizes a third generation P2P net. It protects your
// privacy while you are connected and makes you not trackable, hiding
// your identity (ip) and crypting everything you are sending/receiving
// from others.

// Copyright (C) 2004  Roberto Rossi

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

package ants.p2p.gui;

import org.apache.log4j.*;
import kerjodando.vincent.getfile;
import kerjodando.vincent.Common;
import ants.p2p.NeighbourAnt;
import ants.p2p.query.*;
import ants.p2p.utils.addresses.*;

import java.beans.*;
import java.util.*;

public class ConnectionManager extends Thread implements PropertyChangeListener {
	ConnectionAntPanel cap;

	public static int timeout = 10000;
	public static double freeSlots = 1.0 / 3.0;

	/*
	 * 07-07-10 public static long lastGWebCacheUpdate = 0; public static long
	 * lastGWebCacheFetch = 0; public static boolean publishIpOnGWebCache =
	 * false; public static boolean searchIpOnGWebCache = true;
	 */
	boolean terminate = false;

	static Logger _logger = Logger.getLogger(ConnectionManager.class.getName());

	public ConnectionManager(ConnectionAntPanel cap) {
		super();
		this.cap = cap;
		this.setPriority(1);
	}

	public void propertyChange(PropertyChangeEvent e) {
		// Nothing
	}

	public void terminate() {
		this.terminate = true;
	}

	public void ConnectTo(ConnectingThreadManager tm, String sRemote, int port,
			String sURI) {
		cap.warriorAnt.ConnectToNeighBours(tm, sRemote, port, sURI);
	}

	public void run() {
		// long lastSearchedIrc = 0;
		ConnectingThreadManager tm = new ConnectingThreadManager(this);
		long lastConnectTrustedPeers = 0;
		String[] sarrIps = getfile.getIps().split("\\|", -1);
		for (int i = 0; i < sarrIps.length; ++i) {
			String si = sarrIps[i];
			int i1 = si.lastIndexOf('.');
			if (i1 > 0) {
				sarrIps[i] = si.substring(0, i1);
			}
		}
		while (!terminate) {
			try {
				/*
				 * 07-07-10 if (publishIpOnGWebCache &&
				 * (System.currentTimeMillis() - lastGWebCacheUpdate > 65 * 60 *
				 * 1000)) {
				 * BootstrapServerManager.instance().sendUpdatesAsyncV2(new
				 * ServerInfo( "", this.cap.getLocalStringAddress(), new
				 * Integer(this.cap.getWarriorAnt().getServerPort()), ""));
				 * lastGWebCacheUpdate = System.currentTimeMillis(); }
				 */
				while (!terminate
						&& cap.warriorAnt.getNeighboursNumber() < cap.warriorAnt
								.getMaxNeighbours()
								- Math.floor(freeSlots
										* cap.warriorAnt.getMaxNeighbours())) {
					/*
					 * 07-07-10 if (this.cap.ircBot != null &&
					 * this.cap.ircBot.isConnected() &&
					 * !this.cap.isFirewallChecked() &&
					 * this.cap.searchPeersOnIRC) { try { User[] users =
					 * cap.ircBot.getUsers(ConnectionAntPanel.ircChannel); if
					 * (users.length > 1) { int userIndex = (int) (Math.random() *
					 * users.length); while
					 * (users[userIndex].equals(ConnectionAntPanel.nick) &&
					 * users.length > 1) { userIndex = (int) (Math.random() *
					 * users.length); }
					 * cap.ircBot.sendCTCPCommand(users[userIndex].getNick(),
					 * "ANtsCommandCode:0004 " +
					 * FrameAnt.getInstance(null).ga.cap.
					 * getLocalStringAddress() + ":" +
					 * cap.ircBot.getCaller().warriorAnt. getServerPort());
					 * _logger.info("Sent firewall probe message to: " +
					 * users[userIndex].getNick()); } } catch (Exception ex) {
					 * _logger.error("IRC Error sending firewall probe message: " +
					 * ex.getMessage()); } }
					 */
					long lCurrTimeMills = System.currentTimeMillis();
					// five minutes
					if (lCurrTimeMills - lastConnectTrustedPeers > 30000) {
						// cap.warriorAnt.ConnectToNeighBours("1498",-1);
						lastConnectTrustedPeers = lCurrTimeMills;
						ArrayList peers = InetAddressEngine.getInstance()
								.getTrustedPeers();
						if (peers.size() > 0) {
							for (int x = 0; x < peers.size()
									&& cap.warriorAnt.getNeighboursNumber() < cap.warriorAnt
											.getMaxNeighbours()
											- Math
													.floor(freeSlots
															* cap.warriorAnt
																	.getMaxNeighbours()); x++) {
								ServerInfo peer = (ServerInfo) peers.get(x);
								if (!(peer.getAddress().getHostAddress()
										.equals(
												this.cap.getLocalInetAddress()
														.getHostAddress()) && peer
										.getPort().intValue() == this.cap.warriorAnt
										.getServerPort())) {
									/*
									_logger.info("Trying connecting: "
											+ ((ServerInfo) peers.get(x))
													.getAddress()
													.getHostAddress()
											+ ":"
											+ (((ServerInfo) peers.get(x))
													.getPort().intValue()));
													*/

									boolean bneedc = true;
									synchronized (cap.warriorAnt
											.getNeighbours()) {
										for (int i = 0; i < cap.warriorAnt
												.getNeighbours().size(); i++) {
											NeighbourAnt na = (NeighbourAnt) cap.warriorAnt
													.getNeighbours().get(i);
											if (na.isSTUNTCURICheck(peer
													.getURI())) {
												bneedc = false;
												break;
											}
										}
									}
									if (bneedc) {
										String sRemoteHost = peer.getAddress()
												.getHostAddress();
										int port = peer.getPort().intValue();
										String sSameSubNetIp = null;
										// if it is in the same nat?
										if (Common.ipaddress
												.equals(sRemoteHost)) {
											String[] sap = peer.getOtherIps();
											// to find a suit ip
											boolean bfindsubnetip = false;
											for (int i11 = 0; i11 < sarrIps.length
													&& !bfindsubnetip; ++i11) {
												for (int j11 = 0; j11 < sap.length; ++j11) {
													if (sap[j11]
															.startsWith(sarrIps[i11])) {
														sSameSubNetIp = sap[j11];
														bfindsubnetip = true;
														break;
													}
												}
											}
										}
										tm.Add(peer.getURI(), sRemoteHost,
												sSameSubNetIp, port);
									}
									/*
									 * cap.jTextField5.setText(sInfos.getAddress().getHostAddress());
									 * cap.jTextField6.setText(
									 * (sInfos.getPort().intValue() ) + "");
									 * RefreshAndConnectThread
									 * refreshAndConnectThread = new
									 * RefreshAndConnectThread(this.cap);
									 * refreshAndConnectThread.start();
									 * refreshAndConnectThread.join();
									 */
								}
							}
						}
					}
					/*
					 * peers =
					 * InetAddressEngine.getRandomPeersWithFreeSlots(InetAddressEngine.peersToSendback,
					 * false); _logger.info("Looking for
					 * peers!!!"+peers.size()); if (peers.size() > 0) { for (int
					 * x = 0; x < peers.size() &&
					 * cap.warriorAnt.getNeighboursNumber() <
					 * cap.warriorAnt.getMaxNeighbours() -
					 * Math.floor(freeSlots*cap.warriorAnt.getMaxNeighbours());
					 * x++) { ServerInfo peer = (ServerInfo) peers.get(x); if (!
					 * (peer.getAddress().getHostAddress().equals(this.cap.
					 * getLocalInetAddress().getHostAddress()) &&
					 * peer.getPort().intValue() ==
					 * this.cap.warriorAnt.getServerPort())) {
					 * _logger.info("Trying retrieving peers info from: " + (
					 * (ServerInfo) peers.get(x)). getAddress().
					 * getHostAddress() + ":" + ( ( (ServerInfo)
					 * peers.get(x)).getPort(). intValue())); ServerInfo sInfos =
					 * (ServerInfo) peers.get(x);
					 * cap.jTextField5.setText(sInfos.getAddress().getHostAddress());
					 * cap.jTextField6.setText( (sInfos.getPort().intValue() ) +
					 * ""); RefreshAndConnectThread refreshAndConnectThread =
					 * new RefreshAndConnectThread(this.cap);
					 * refreshAndConnectThread.start();
					 * refreshAndConnectThread.join(); }else{ } } }
					 */
					/*
					 * 07-07-10 else{ lastGWebCacheFetch = 0; }
					 */
					/*
					 * peers =
					 * InetAddressEngine.getRandomIMPeersWithFreeSlots(InetAddressEngine.peersToSendback);
					 * if (peers.size() > 0) { for (int x = 0; x < peers.size() &&
					 * cap.warriorAnt.getNeighboursNumber() <
					 * cap.warriorAnt.getMaxNeighbours() -
					 * Math.floor(freeSlots*cap.warriorAnt.getMaxNeighbours());
					 * x++) { ServerInfo peer = (ServerInfo) peers.get(x); if (!
					 * (peer.getAddress().getHostAddress().equals(this.cap.
					 * getLocalInetAddress().getHostAddress()) &&
					 * peer.getPort().intValue() ==
					 * this.cap.warriorAnt.getServerPort())) {
					 * _logger.info("Trying retrieving peers info from: " + (
					 * (ServerInfo) peers.get(x)). getAddress().
					 * getHostAddress() + ":" + ( ( (ServerInfo)
					 * peers.get(x)).getPort(). intValue()));
					 * 
					 * ServerInfo sInfos = (ServerInfo) peers.get(x);
					 * cap.jTextField5.setText(sInfos.getAddress().getHostAddress());
					 * cap.jTextField6.setText( (sInfos.getPort().intValue() ) +
					 * ""); RefreshAndConnectThread refreshAndConnectThread =
					 * new RefreshAndConnectThread(this.cap);
					 * refreshAndConnectThread.start();
					 * refreshAndConnectThread.join(); } } }
					 */
					/*
					 * if(searchIpOnGWebCache && (System.currentTimeMillis() -
					 * lastGWebCacheFetch > 65*60*1000)){
					 * BootstrapServerManager.instance().resetData();
					 * BootstrapServerManager.instance().fetchEndpointsAsyncV2();
					 * lastGWebCacheFetch=System.currentTimeMillis(); }
					 * if(publishIpOnGWebCache && (System.currentTimeMillis() -
					 * lastGWebCacheUpdate > 65*60*1000)){
					 * BootstrapServerManager.instance().sendUpdatesAsyncV2(new
					 * ServerInfo("", this.cap.getLocalStringAddress(), new
					 * Integer(this.cap.getWarriorAnt().getServerPort()),""));
					 * lastGWebCacheUpdate = System.currentTimeMillis(); }
					 */
					try {
						if (cap.warriorAnt.getNeighboursNumber() > cap.warriorAnt
								.getMaxNeighbours() * 2.0 / 3.0)
							sleep(timeout
									* cap.warriorAnt.getNeighboursNumber());
						else
							sleep(timeout);
					} catch (Exception e) {
						_logger.error("Connection manager sleep Exception: "
								+ e.getMessage());
					}
				}
				try {
					if (cap.warriorAnt.getNeighboursNumber() > cap.warriorAnt
							.getMaxNeighbours() * 2.0 / 3.0)
						sleep(timeout * cap.warriorAnt.getNeighboursNumber());
					else
						sleep(timeout);
				} catch (Exception e) {
					_logger.error("Connection manager sleep Exception: "
							+ e.getMessage());
				}
			} catch (Exception e) {
				_logger.error("Connection manager main cycle error", e);
				try {
					if (cap.warriorAnt.getNeighboursNumber() > cap.warriorAnt
							.getMaxNeighbours() * 2.0 / 3.0)
						sleep(timeout * cap.warriorAnt.getNeighboursNumber());
					else
						sleep(timeout);
				} catch (Exception ex) {
					_logger.error("Connection manager sleep Exception: "
							+ ex.getMessage());
				}
			}
		}
	}
}
